﻿using System;
using System.Windows;
using System.Windows.Controls;

using Supremacy.Diplomacy;

namespace Supremacy.Client
{
    /// <summary>
    /// Interaction logic for DurationEditor.xaml
    /// </summary>
    public partial class DurationEditor : UserControl
    {
        #region Fields
        public static readonly DependencyProperty DurationProperty;
        public static readonly DependencyProperty MinDurationProperty;
        #endregion

        #region Constructors
        static DurationEditor()
        {
            MinDurationProperty = DependencyProperty.Register(
                "MinDuration",
                typeof(int),
                typeof(DurationEditor),
                new PropertyMetadata(
                    Stipulation.ImmediateDuration,
                    OnMinDurationChanged,
                    CoerceMinDuration),
                ValidateDuration);
            DurationProperty = DependencyProperty.Register(
                "Duration",
                typeof(int),
                typeof(DurationEditor),
                new PropertyMetadata(
                    Stipulation.ImmediateDuration,
                    OnDurationChanged,
                    CoerceDuration),
                ValidateDuration);
        }

        public DurationEditor() : this(Stipulation.ImmediateDuration) {}

        public DurationEditor(int minDuration)
        {
            InitializeComponent();
            this.MinDuration = minDuration;
            this.UpdateOptions();
            this.UpdateSelection();
        }
        #endregion

        #region Properties
        public int MinDuration
        {
            get { return (int)GetValue(MinDurationProperty); }
            set { SetValue(MinDurationProperty, value); }
        }

        public int Duration
        {
            get { return (int)GetValue(DurationProperty); }
            set { SetValue(DurationProperty, value); }
        }
        #endregion

        #region Methods
        private static object CoerceDuration(DependencyObject d, object baseValue)
        {
            DurationEditor source = d as DurationEditor;
            if (source != null)
            {
                int duration = (int)baseValue;
                if (((duration % Stipulation.DurationStepSize) != 0)
                    && (duration != Stipulation.ImmediateDuration)
                    && (duration != Stipulation.IndefiniteDuration))
                {
                    duration -= (duration % Stipulation.DurationStepSize);
                }
                if (duration < source.MinDuration)
                {
                    duration = source.MinDuration;
                }
                else if (duration > Stipulation.IndefiniteDuration)
                {
                    duration = Stipulation.IndefiniteDuration;
                }
                return duration;
            }
            return baseValue;
        }

        private static object CoerceMinDuration(DependencyObject d, object baseValue)
        {
            int minDuration = (int)baseValue;
            if ((minDuration % Stipulation.DurationStepSize) != 0)
                minDuration -= (minDuration % Stipulation.DurationStepSize);
            if (minDuration < Stipulation.ImmediateDuration)
                minDuration = Stipulation.ImmediateDuration;
            else if (minDuration > Stipulation.IndefiniteDuration)
                minDuration = Stipulation.IndefiniteDuration;
            return minDuration;
        }

        private static void OnDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DurationEditor source = d as DurationEditor;
            if (source != null)
            {
                source.UpdateSelection();
            }
        }

        private void UpdateSelection()
        {
            if (this.Duration == Stipulation.ImmediateDuration)
            {
                this.ImmediateButton.IsChecked = true;
            }
            else if (this.Duration == Stipulation.IndefiniteDuration)
            {
                this.IndefiniteButton.IsChecked = true;
            }
            else
            {
                if (CustomDurationList.SelectedIndex == -1)
                {
                    int customValueIndex = -1;
                    for (int i = this.CustomDurationList.Items.Count - 1; i >= 0; i--)
                    {
                        if ((int)this.CustomDurationList.Items[i] <= this.Duration)
                        {
                            customValueIndex = i;
                            break;
                        }
                    }
                    if (customValueIndex == -1)
                    {
                        this.CustomButton.IsEnabled = false;
                        this.CustomButton.IsChecked = false;
                        this.Duration = this.MinDuration;
                    }
                    else
                    {
                        this.CustomButton.IsEnabled = true;
                        this.CustomButton.IsChecked = true;
                    }
                    this.CustomDurationList.SelectedIndex = customValueIndex;
                }
            }
        }

        private static void OnMinDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DurationEditor source = d as DurationEditor;
            if (source != null)
            {
                source.UpdateOptions();
            }
        }

        private void UpdateOptions()
        {
            this.CustomDurationList.Items.Clear();
            int firstStep = (this.MinDuration > Stipulation.DurationStepSize)
                ? Stipulation.DurationStepSize * ((this.MinDuration / Stipulation.DurationStepSize) + 1)
                : Stipulation.DurationStepSize;
            for (int value = firstStep; value < Stipulation.IndefiniteDuration; value += Stipulation.DurationStepSize)
            {
                this.CustomDurationList.Items.Add(value);
            }
            if ((this.CustomDurationList.SelectedIndex < 0) && (this.CustomDurationList.Items.Count > 0))
            {
                this.CustomDurationList.SelectedIndex = 0;
            }
            this.ImmediateButton.IsEnabled = (this.MinDuration == Stipulation.ImmediateDuration);
            this.CustomButton.IsEnabled = (CustomDurationList.Items.Count > 0);
            if (this.ImmediateButton.IsChecked.HasValue && this.ImmediateButton.IsChecked.Value)
            {
                if (!this.ImmediateButton.IsEnabled)
                {
                    if (this.IndefiniteButton.IsEnabled)
                    {
                        this.IndefiniteButton.IsChecked = true;
                    }
                    if (this.CustomButton.IsEnabled)
                    {
                        this.CustomButton.IsChecked = true;
                    }
                }
            }
            else if (this.CustomButton.IsChecked.HasValue && this.CustomButton.IsChecked.Value)
            {
                if (!this.CustomButton.IsEnabled)
                {
                    if (this.IndefiniteButton.IsEnabled)
                    {
                        this.IndefiniteButton.IsChecked = true;
                    }
                    if (this.ImmediateButton.IsEnabled)
                    {
                        this.ImmediateButton.IsChecked = true;
                    }
                }
            }
            else
            {
                this.IndefiniteButton.IsChecked = this.IndefiniteButton.IsEnabled;
            }
        }

        private static bool ValidateDuration(object value)
        {
            int duration = (int)value;
            if (((duration % Stipulation.DurationStepSize) != 0)
                && (duration != Stipulation.ImmediateDuration)
                && (duration != Stipulation.IndefiniteDuration))
            {
                return false;
            }
            if (duration < Stipulation.ImmediateDuration)
            {
                return false;
            }
            if (duration > Stipulation.IndefiniteDuration)
            {
                return false;
            }
            return true;
        }

        private void CustomButton_Checked(object sender, RoutedEventArgs e)
        {
            if (this.CustomDurationList.SelectedIndex == -1)
            {
                this.Duration = (int)this.CustomDurationList.Items[0];
                this.CustomDurationList.SelectedIndex = 0;
            }
            else
            {
                this.Duration = (int)this.CustomDurationList.SelectedItem;
            }
        }

        private void CustomDurationList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if ((this.CustomDurationList.SelectedIndex != -1)
                && this.CustomButton.IsChecked.HasValue
                && this.CustomButton.IsChecked.Value)
            {
                this.Duration = (int)this.CustomDurationList.SelectedItem;
            }
        }

        private void ImmediateButton_Checked(object sender, RoutedEventArgs e)
        {
            this.Duration = Stipulation.ImmediateDuration;
        }

        private void IndefiniteButton_Checked(object sender, RoutedEventArgs e)
        {
            this.Duration = Stipulation.IndefiniteDuration;
        }
        #endregion
    }
}